<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
                      "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
    <title>Building an Authorization System in Zend Framework - Zend Framework Manual</title>

    <link href="../css/shCore.css" rel="stylesheet" type="text/css" />
    <link href="../css/shThemeDefault.css" rel="stylesheet" type="text/css" />
    <link href="../css/styles.css" media="all" rel="stylesheet" type="text/css" />
</head>
<body>
<h1>Zend Framework</h1>
<h2>Programmer's Reference Guide</h2>
<ul>
    <li><a href="../en/learning.multiuser.authorization.html">Inglês (English)</a></li>
    <li><a href="../pt-br/learning.multiuser.authorization.html">Português Brasileiro (Brazilian Portuguese)</a></li>
</ul>
<table width="100%">
    <tr valign="top">
        <td width="85%">
            <table width="100%">
                <tr>
                    <td width="25%" style="text-align: left;">
                    <a href="learning.multiuser.authentication.html">Authenticating Users in Zend Framework</a>
                    </td>

                    <td width="50%" style="text-align: center;">
                        <div class="up"><span class="up"><a href="learning.multiuser.html">Iniciando com o Zend_Session, Zend_Auth, e Zend_Acl</a></span><br />
                        <span class="home"><a href="manual.html">Guia de Refer&ecirc;ncia do Programador</a></span></div>
                    </td>

                    <td width="25%" style="text-align: right;">
                        <div class="next" style="text-align: right; float: right;"><a href="learning.lucene.html">Iniciando com o Zend_Search_Lucene</a></div>
                    </td>
                </tr>
            </table>
<hr />
<div id="learning.multiuser.authorization" class="section"><div class="info"><h1 class="title">Building an Authorization System in Zend Framework</h1></div>
    

    <div class="section" id="learning.multiuser.authorization.intro"><div class="info"><h1 class="title">Introduction to Authorization</h1></div>
        

        <p class="para">
            After a user has been identified as being authentic, an application can go about its
            business of providing some useful and desirable resources to a consumer. In many cases,
            applications might contain different resource types, with some resources having stricter
            rules regarding access. This process of determining who has access to which resources is
            the process of &quot;authorization&quot;. Authorization in its simplest form is the composition of
            these elements:
        </p>

        <ul class="itemizedlist">
            <li class="listitem">
                <p class="para">
                    the identity whom wishes to be granted access
                </p>
            </li>

            <li class="listitem">
                <p class="para">
                    the resource the identity is asking permission to consume
                </p>
            </li>

            <li class="listitem">
                <p class="para">
                    and optionally, what the identity is privileged to do with the resource
                </p>
            </li>
        </ul>

        <p class="para">
            In Zend Framework, the <span class="classname">Zend_Acl</span> component handles the task of
            building a tree of roles, resources and privileges to manage and query authorization
            requests against.
        </p>
    </div>

    <div class="section" id="learning.multiuser.authorization.basic-usage"><div class="info"><h1 class="title">Basic Usage of Zend_Acl</h1></div>
        



        <p class="para">
            When using <span class="classname">Zend_Acl</span>, any models can serve as roles or resources
            by simply implementing the proper interface. To be used in a role capacity, the class
            must implement the <span class="classname">Zend_Acl_Role_Interface</span>, which requires only
             <span class="methodname">getRoleId()</span>. To be used in a resource capacity, a class must
            implement the <span class="classname">Zend_Acl_Resource_Interface</span> which similarly
            requires the class implement the  <span class="methodname">getResourceId()</span> method.
        </p>

        <p class="para">
            Demonstrated below is a simple user model. This model can take part in our
            <acronym class="acronym">ACL</acronym> system simply by implementing the
            <span class="classname">Zend_Acl_Role_Interface</span>. The method
             <span class="methodname">getRoleId()</span> will return the id &quot;guest&quot; when an ID is not known,
            or it will return the role ID that was assigned to this actual user object. This value
            can effectively come from anywhere, a static definition or perhaps dynamically from the
            users database role itself.
        </p>

        <pre class="programlisting brush: php">
class Default_Model_User implements Zend_Acl_Role_Interface
{
    protected $_aclRoleId = null;

    public function getRoleId()
    {
        if ($this-&gt;_aclRoleId == null) {
            return &#039;guest&#039;;
        }

        return $this-&gt;_aclRoleId;
    }
}
</pre>


        <p class="para">
            While the concept of a user as a role is pretty straight forward, your application
            might choose to have any other models in your system as a potential &quot;resource&quot; to be
            consumed in this <acronym class="acronym">ACL</acronym> system. For simplicity, we&#039;ll use the example
            of a blog post. Since the type of the resource is tied to the type of the object,
            this class will only return &#039;blogPost&#039; as the resource ID in this system. Naturally,
            this value can be dynamic if your system requires it to be so.
        </p>

        <pre class="programlisting brush: php">
class Default_Model_BlogPost implements Zend_Acl_Resource_Interface
{
    public function getResourceId()
    {
        return &#039;blogPost&#039;;
    }
}
</pre>


        <p class="para">
            Now that we have at least a role and a resource, we can go about defining the rules
            of the <acronym class="acronym">ACL</acronym> system. These rules will be consulted when the system
            receives a query about what is possible given a certain role, resources, and optionally
            a privilege.
        </p>

        <p class="para">
            Lets assume the following rules:
        </p>

        <pre class="programlisting brush: php">
$acl = new Zend_Acl();

// setup the various roles in our system
$acl-&gt;addRole(&#039;guest&#039;);
// owner inherits all of the rules of guest
$acl-&gt;addRole(&#039;owner&#039;, &#039;guest&#039;);

// add the resources
$acl-&gt;addResource(&#039;blogPost&#039;);

// add privileges to roles and resource combinations
$acl-&gt;allow(&#039;guest&#039;, &#039;blogPost&#039;, &#039;view&#039;);
$acl-&gt;allow(&#039;owner&#039;, &#039;blogPost&#039;, &#039;post&#039;);
$acl-&gt;allow(&#039;owner&#039;, &#039;blogPost&#039;, &#039;publish&#039;);
</pre>


        <p class="para">
            The above rules are quite simple: a guest role and an owner role exist; as does a
            blogPost type resource. Guests are allowed to view blog posts, and owners are
            allowed to post and publish blog posts. To query this system one might do any of
            the following:
        </p>

        <pre class="programlisting brush: php">
// assume the user model is of type guest resource
$guestUser = new Default_Model_User();
$ownerUser = new Default_Model_Owner(&#039;OwnersUsername&#039;);

$post = new Default_Model_BlogPost();

$acl-&gt;isAllowed($guestUser, $post, &#039;view&#039;); // true
$acl-&gt;isAllowed($ownerUser, $post, &#039;view&#039;); // true
$acl-&gt;isAllowed($guestUser, $post, &#039;post&#039;); // false
$acl-&gt;isAllowed($ownerUser, $post, &#039;post&#039;); // true
</pre>


        <p class="para">
            As you can see, the above rules exercise whether owners and guests can view posts,
            which they can, or post new posts, which owners can and guests cannot. But as you
            might expect this type of system might not be as dynamic as we wish it to be.
            What if we want to ensure a specific owner actual owns a very specific blog post
            before allowing him to publish it? In other words, we want to ensure that only post
            owners have the ability to publish their own posts.
        </p>

        <p class="para">
            This is where assertions come in. Assertions are methods that will be called out to
            when the static rule checking is simply not enough. When registering an assertion
            object this object will be consulted to determine, typically dynamically, if some
            roles has access to some resource, with some optional privlidge that can only be
            answered by the logic within the assertion. For this example, we&#039;ll use the following
            assertion:
        </p>

        <pre class="programlisting brush: php">
class OwnerCanPublishBlogPostAssertion implements Zend_Acl_Assert_Interface
{
    /**
     * This assertion should receive the actual User and BlogPost objects.
     *
     * @param Zend_Acl $acl
     * @param Zend_Acl_Role_Interface $user
     * @param Zend_Acl_Resource_Interface $blogPost
     * @param $privilege
     * @return bool
     */
    public function assert(Zend_Acl $acl,
                           Zend_Acl_Role_Interface $user = null,
                           Zend_Acl_Resource_Interface $blogPost = null,
                           $privilege = null)
    {
        if (!$user instanceof Default_Model_User) {
            throw new Exception(__CLASS__
                              . &#039;::&#039;
                              . __METHOD__
                              . &#039; expects the role to be&#039;
                              . &#039; an instance of User&#039;);
        }

        if (!$blogPost instanceof Default_Model_BlogPost) {
            throw new Exception(__CLASS__
                              . &#039;::&#039;
                              . __METHOD__
                              . &#039; expects the resource to be&#039;
                              . &#039; an instance of BlogPost&#039;);
        }

        // if role is publisher, he can always modify a post
        if ($user-&gt;getRoleId() == &#039;publisher&#039;) {
            return true;
        }

        // check to ensure that everyone else is only modifying their own post
        if ($user-&gt;id != null &amp;&amp; $blogPost-&gt;ownerUserId == $user-&gt;id) {
            return true;
        } else {
            return false;
        }
    }
}
</pre>


        <p class="para">
            To hook this into our <acronym class="acronym">ACL</acronym> system, we would do the following:
        </p>

        <pre class="programlisting brush: php">
// replace this:
//   $acl-&gt;allow(&#039;owner&#039;, &#039;blogPost&#039;, &#039;publish&#039;);
// with this:
$acl-&gt;allow(&#039;owner&#039;,
            &#039;blogPost&#039;,
            &#039;publish&#039;,
            new OwnerCanPublishBlogPostAssertion());

// lets also add the role of a &quot;publisher&quot; who has access to everything
$acl-&gt;allow(&#039;publisher&#039;, &#039;blogPost&#039;, &#039;publish&#039;);
</pre>


        <p class="para">
            Now, anytime the <acronym class="acronym">ACL</acronym> is consulted about whether or not an owner
            can publish a specific blog post, this assertion will be run. This assertion will
            ensure that unless the role type is &#039;publisher&#039; the owner role must be logically
            tied to the blog post in question. In this example, we check to see that the
            <span class="property">ownerUserId</span> property of the blog post matches the id of the
            owner passed in.
        </p>
    </div>
</div>
        <hr />

            <table width="100%">
                <tr>
                    <td width="25%" style="text-align: left;">
                    <a href="learning.multiuser.authentication.html">Authenticating Users in Zend Framework</a>
                    </td>

                    <td width="50%" style="text-align: center;">
                        <div class="up"><span class="up"><a href="learning.multiuser.html">Iniciando com o Zend_Session, Zend_Auth, e Zend_Acl</a></span><br />
                        <span class="home"><a href="manual.html">Guia de Refer&ecirc;ncia do Programador</a></span></div>
                    </td>

                    <td width="25%" style="text-align: right;">
                        <div class="next" style="text-align: right; float: right;"><a href="learning.lucene.html">Iniciando com o Zend_Search_Lucene</a></div>
                    </td>
                </tr>
            </table>
</td>
        <td style="font-size: smaller;" width="15%"> <style type="text/css">
#leftbar {
	float: left;
	width: 186px;
	padding: 5px;
	font-size: smaller;
}
ul.toc {
	margin: 0px 5px 5px 5px;
	padding: 0px;
}
ul.toc li {
	font-size: 85%;
	margin: 1px 0 1px 1px;
	padding: 1px 0 1px 11px;
	list-style-type: none;
	background-repeat: no-repeat;
	background-position: center left;
}
ul.toc li.header {
	font-size: 115%;
	padding: 5px 0px 5px 11px;
	border-bottom: 1px solid #cccccc;
	margin-bottom: 5px;
}
ul.toc li.active {
	font-weight: bold;
}
ul.toc li a {
	text-decoration: none;
}
ul.toc li a:hover {
	text-decoration: underline;
}
</style>
 <ul class="toc">
  <li class="header home"><a href="manual.html">Guia de Refer&ecirc;ncia do Programador</a></li>
  <li class="header up"><a href="manual.html">Guia de Refer&ecirc;ncia do Programador</a></li>
  <li class="header up"><a href="learning.html">Conhecendo o Zend Framework</a></li>
  <li class="header up"><a href="learning.multiuser.html">Iniciando com o Zend_Session, Zend_Auth, e Zend_Acl</a></li>
  <li><a href="learning.multiuser.intro.html">Building Multi-User Applications With Zend Framework</a></li>
  <li><a href="learning.multiuser.sessions.html">Managing User Sessions In ZF</a></li>
  <li><a href="learning.multiuser.authentication.html">Authenticating Users in Zend Framework</a></li>
  <li class="active"><a href="learning.multiuser.authorization.html">Building an Authorization System in Zend Framework</a></li>
 </ul>
 </td>
    </tr>
</table>

<script type="text/javascript" src="../js/shCore.js"></script>
<script type="text/javascript" src="../js/shAutoloader.js"></script>
<script type="text/javascript" src="../js/main.js"></script>

</body>
</html>